﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XRpgLibrary.Events
{
    /// <summary>
    /// Basic routing of "string" cast events, can queue up lists of events to be fired
    /// </summary>
    public class EventRouter
    {
        public static EventRouter Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new EventRouter();
                return _instance;
            }
        }

        /// <summary>
        /// A type of delegate for queue
        /// </summary>
        public delegate void eventDelegate();

        /// <summary>
        /// A type of delegate for queue
        /// </summary>
        public delegate void objectEventDelegate(ObjectEvent objEvent);

        /// <summary>
        /// Add an event to be fired.
        /// </summary>
        public void add(string eventName, eventDelegate callToFunction)
        {
            List<eventDelegate> _list;
            list.TryGetValue(eventName, out _list);
            if (_list != null)
                _list.Add(callToFunction);
            else
            {
                _list = new List<eventDelegate>();
                _list.Add(callToFunction);
                list.Add(eventName, _list);
            }
        }

        /// <summary>
        /// Add an event to be fired.
        /// </summary>
        public void add(string eventName, objectEventDelegate callToFunction)
        {
            List<objectEventDelegate> _list;
            objectEventList.TryGetValue(eventName, out _list);
            if (_list != null)
                _list.Add(callToFunction);
            else
            {
                _list = new List<objectEventDelegate>();
                _list.Add(callToFunction);
                objectEventList.Add(eventName, _list);
            }
        }
        /// <summary>
        /// Remove an event
        /// </summary>
        public bool remove(string eventName, eventDelegate callToFunction)
        {
            List<eventDelegate> _list;
            list.TryGetValue(eventName, out _list);
            if (_list == null)
                return false;

            foreach (eventDelegate _event in _list)
            {
                if (_event == callToFunction)
                {
                    _list.Remove(_event);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// Remove an event
        /// </summary>
        public bool remove(string eventName, objectEventDelegate callToFunction)
        {
            List<objectEventDelegate> _list;
            objectEventList.TryGetValue(eventName, out _list);
            if (_list == null)
                return false;

            foreach (objectEventDelegate _event in _list)
            {
                if (_event == callToFunction)
                {
                    _list.Remove(_event);
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// update the event router with a particular event, all queued events linked to this event name will be fired
        /// </summary>
        public void update(string eventName)
        {
            List<eventDelegate> _list;
            list.TryGetValue(eventName, out _list);
            if (_list != null)
            {
                List<eventDelegate> _list2 = new List<eventDelegate>();
                int i = _list.Count;
                while (i > 0)
                {
                    if (!_list2.Contains(_list[i - 1]))
                    {
                        (_list[i - 1] as eventDelegate)();
                        try
                        {
                            _list2.Add(_list[i - 1]);
                        }
                        catch
                        {
                        }
                    }
                    i--;
                }
                //  foreach (eventDelegate _event in _list)
                //        _event();
            }
        }
        /// <summary>
        /// update the event router with a particular event, all queued events linked to this event name will be fired
        /// </summary>
        public void update(ObjectEvent objEvent)
        {
            List<objectEventDelegate> _list;
            objectEventList.TryGetValue(objEvent.Name, out _list);
            if (_list != null)
            {
                foreach (objectEventDelegate _event in _list)
                    _event(objEvent);
            }
        }
        

        private static EventRouter _instance = null;
        private Dictionary<string, List<eventDelegate>> list = new Dictionary<string, List<eventDelegate>>();
        private Dictionary<string, List<objectEventDelegate>> objectEventList = new Dictionary<string, List<objectEventDelegate>>();
        public class ObjectEvent
        {
            public ObjectEvent(string name, object data)
            {
                Name = name;
                Data = data;
            }
            public string Name = "";
            public object Data;
        }
    }
}
